home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Files / Utils / Brian's Extensions / SWLightingSquares.c < prev    next >
Encoding:
Text File  |  2000-10-06  |  28.2 KB  |  799 lines  |  [TEXT/CWIE]

  1. /*  -----------------------------------------------------------------------------------
  2.     -----------------------------------------------------------------------------------
  3.     SWLightingSquares.c
  4.     
  5.     by Brian Roddy
  6.     
  7.     5/20/97
  8.  
  9.     
  10.     ** N.B. These functions are still experimental.  They work fine, but the public API
  11.        needs work to achieve better effects and uses.
  12.  
  13.  
  14.     These routines are for an alternative style of getting lighting effects.  It's
  15.     main function is a Screen Blitting procedures that takes the offscreen work area
  16.     and colors it as it copies it on screen.  Thus the parts copied on screen can 
  17.     be made darker or lighter or a little reddish, etc.  
  18.     
  19.     To support a feeling of lights, we divide the screen into a map of tiny squares 
  20.     and associate a color and a level with each square.  As we blit onto the screen,
  21.     we use this map to color the image.  The result is that the screen image looks
  22.     nicely colorized.  Imagine each square having a colored gel placed over top of 
  23.     it.
  24.     
  25.     The smaller the squares in our map, the finer the grain of lighting but the greater
  26.     the overhead.  More space and speed are required.  We also provide routines for setting 
  27.     and managing this lighting map, including setting light levels and combining 
  28.     lights (so blue lights and yellow lights will become greenish lights as they overlap).
  29.  
  30.     These functions make use of the translucency table functions found in 
  31.     "SWTranslucentBlitters.c" and therefore that file needs to be present for this to
  32.     work.
  33.  
  34.     Use SWInitializeLightingSquares(spriteWorldPtr, 8); to initialize the use of squares.
  35.     8 in this case is the size of the squares in pixels.  
  36.     
  37.     Use:
  38.         SWSetLightingSquare(spriteWorldPtr, col, row, 
  39.                              color, opacity,
  40.                              relativeP, makeDirtyP);
  41.     to set a cell's value.  Opacity is the translucency levels (as in the translucent blitters).
  42.     relativeP is a boolean specifying whether to set the color and level directly or to blend
  43.     it together with what is already in the cell.   makeDirtyP forces sprite world to redraw
  44.     that cell on the screen during the next draw loop.
  45.     
  46.     Use:
  47.         SWLightUpArea (spriteWorldPtr, col, row, 
  48.                         color,  level
  49.                         bigLightP);
  50.     to light up an area around a cell.  This is good for spotlights.  bigLightP makes the light
  51.     really big.  Note that this just calls     SWSetLightingSquare repeatedly.        
  52.  
  53.     SWDarkenLightingSquares (spriteWorldPtr); will blend black into every square in the
  54.     grid to darken everything.  This is a good example of how to achieve a lighting effect
  55.     with these squares.
  56.     
  57.     Use SWExitLightingSquares (); to free up the tables when quitting.  
  58.     
  59.     You may use these routines in a scrolling game, provided that you scroll in 
  60.     multiples of the lighting grid.
  61.  
  62.     The Lit Breakout Demo is an example of how to use these functions in an app.
  63.  
  64.  
  65.     -------------------------------------------------------------------------------------
  66.     Implementation Notes:
  67.  
  68.     The engine for all of this is the code for blitting Tinted Rects in 8 bit or in 16 bit 
  69.     mode.  There are straight C versions as well as versions that use optimize PowerPC 
  70.     assembly. 
  71.          
  72.     This source code is available for free use.
  73.     ----------------------------------------------------------------------------------- 
  74.     ----------------------------------------------------------------------------------- */
  75.  
  76.  
  77. ///--------------------------------------------------------------------------------------
  78. // Includes
  79. ///--------------------------------------------------------------------------------------
  80.  
  81. #include <SWTranslucentBlitters.h>
  82. #include <SWLightingSquares.h>
  83. #include <SWGameUtils.h>
  84.  
  85. unsigned long *gLitSquareColorTable;
  86. unsigned long *gLitSquareLevelTable;
  87. int gLightingSquareRows, gLightingSquareColumns;
  88. int SWLitSquareSize    = 8;
  89.  
  90. unsigned long gBlackColor;
  91.  
  92. #pragma mark ----------- Public API -------------
  93. SW_FUNC OSErr     SWInitializeLightingSquares (SpriteWorldPtr spriteWorldP, 
  94.                                             int squareSize) {
  95.     long                arraySize;
  96.     OSErr                err = noErr;
  97.     
  98.     SWLitSquareSize = squareSize;
  99.     gLightingSquareColumns = ((spriteWorldP->windRect.right - spriteWorldP->windRect.left) / SWLitSquareSize) + 1;
  100.     gLightingSquareRows = ((spriteWorldP->windRect.bottom - spriteWorldP->windRect.top) / SWLitSquareSize) + 1;
  101.     
  102.     SWExitLightingSquares ();
  103.     
  104.     if (err == noErr) {
  105.         if (spriteWorldP->pixelDepth == 8) {
  106.             SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixie8BitLitRectDrawProc);
  107.             CreateCLUTTable();
  108.             gBlackColor = ColorToIndex(0,0,0);
  109.         } else if (spriteWorldP->pixelDepth == 16) {
  110.             SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixie16BitLitRectDrawProc);
  111.             gBlackColor = 0x0000;
  112.         
  113.         }
  114.         else
  115.             err = kWrongDepthErr;
  116.     }
  117.  
  118.     if (err == noErr) {
  119.         arraySize = gLightingSquareColumns * gLightingSquareRows * sizeof(unsigned long);
  120.         gLitSquareColorTable = (unsigned long *)NewPtr(arraySize);
  121.         err = MemError();
  122.     }
  123.     
  124.     if (err == noErr) {
  125.         arraySize = gLightingSquareColumns * gLightingSquareRows * sizeof(unsigned long);
  126.         gLitSquareLevelTable = (unsigned long *)NewPtr(arraySize);
  127.         err = MemError();
  128.     }
  129.     
  130.     return err;
  131. }
  132.  
  133. SW_FUNC void     SWExitLightingSquares ()
  134. {
  135.     // Only do this if we've created a table.
  136.     if (gLitSquareColorTable != NULL) DisposePtr((Ptr)gLitSquareColorTable);
  137.     if (gLitSquareLevelTable != NULL) DisposePtr((Ptr)gLitSquareLevelTable);
  138. }
  139.  
  140.  
  141.  
  142. ///--------------------------------------------------------------------------------------
  143. ///--------------------------------------------------------------------------------------
  144. /// Table Management Functions
  145. ///--------------------------------------------------------------------------------------
  146. ///--------------------------------------------------------------------------------------
  147.  
  148. SW_FUNC void SWSetLightingSquare(SpriteWorldPtr swp, int col, int row, 
  149.                          unsigned long color, unsigned long level,
  150.                          Boolean relative, Boolean makeDirty) {
  151.     long index, curColor, curLevel, newColor, newLevel;
  152.     Rect changedRect;
  153.     
  154.     // Bounds Checking
  155.     if (! ((row < 0) || 
  156.            (col < 0) || 
  157.            (row >= gLightingSquareRows) ||
  158.            (col >= gLightingSquareColumns))) {
  159.         
  160.         int maxLevel;
  161.         if (swp->pixelDepth == 8) 
  162.             maxLevel = gNumberOf8BitTranslucencyLevels;
  163.         else
  164.             maxLevel = 32;
  165.         if (level < 0) level = 0;
  166.         if (level >= maxLevel) level = (maxLevel - 1);
  167.         
  168.         // Compute the data structure
  169.         index = ((row * gLightingSquareColumns) + col);
  170.         curColor = gLitSquareColorTable[index];
  171.         curLevel = gLitSquareLevelTable[index];
  172.         
  173.         if (relative) {
  174.             if (swp->pixelDepth == 8) { 
  175.                 newColor = Blend8BitPixels(level, curColor, color);
  176.             } else {
  177.                 newColor = Blend16BitPixels(level, curColor, color);
  178.             }
  179.             
  180.             if (newColor == curColor) 
  181.                 newColor = color;
  182.  
  183.             newLevel = (curLevel + level) / 2;
  184.             if (newLevel == curLevel) 
  185.                 newLevel = level;
  186.                 
  187.         } else {
  188.             newColor = color;
  189.             newLevel = level;
  190.         }
  191.             
  192.         // And if the value is different
  193.         if ((curColor != newColor) ||
  194.             (curLevel != newLevel)) {
  195.  
  196.             // Update the data structure
  197.             gLitSquareColorTable[index] = newColor;
  198.             gLitSquareLevelTable[index] = newLevel;
  199.             
  200.             if (makeDirty) {
  201.                 // And tell spriteworld that the square is dirty
  202.                 changedRect.top = row * SWLitSquareSize;
  203.                 changedRect.bottom = ((row + 1) * SWLitSquareSize);
  204.                 changedRect.left = col * SWLitSquareSize;
  205.                 changedRect.right = ((col + 1) * SWLitSquareSize);
  206.                 SWFlagRectAsChanged(swp, &changedRect);
  207.             }
  208.         }
  209.     }
  210. }
  211.  
  212. ///--------------------------------------------------------------------------------------
  213. ///---- SWDarkenLightingSquares.
  214. ///
  215. /// A utility function to do light fading over time.
  216.  
  217. SW_FUNC void SWDarkenLightingSquares (SpriteWorldPtr swp)
  218. {
  219.     int row, col, index = 0;
  220.     int maxLevel;
  221.     
  222.     if (swp->pixelDepth == 8)
  223.         maxLevel = gNumberOf8BitTranslucencyLevels - 1;
  224.     else
  225.         maxLevel = 30;
  226.     
  227.     for (row = 0; row < gLightingSquareRows; row++)
  228.         for (col = 0; col < gLightingSquareColumns; col++) {
  229.             if ((gLitSquareColorTable[index] != gBlackColor) ||
  230.                 (gLitSquareLevelTable[index] != maxLevel)) {
  231.                 int index = ((row * gLightingSquareColumns) + col);
  232.                 int curLevel = gLitSquareLevelTable[index];
  233.  
  234.                 SWSetLightingSquare(swp, col, row, gBlackColor, maxLevel, (curLevel != maxLevel), true);
  235.             }
  236.             index++;
  237.         }
  238. }
  239.  
  240.  
  241. ///--------------------------------------------------------------------------------------
  242. ///--------------------------------------------------------------------------------------
  243.  
  244. SW_FUNC void SWLightUpArea (
  245.     SpriteWorldPtr swp, 
  246.     int col, 
  247.     int row, 
  248.     unsigned long lightColor, 
  249.     int lightLevel, 
  250.     Boolean BigLight) {
  251.  
  252.     // Light up the tiles around the sprite.  Light up the center sprite and
  253.     // adjacent ones really bright, Light up the four diagonally adjacent ones
  254.     // fairly bright. 
  255.     
  256.     // Calculate the light levels
  257.     int lightLevelBorder = lightLevel;
  258.     int lightLevelMiddle = lightLevelBorder; // + RandomNumber(2);
  259.     
  260.     Boolean blendIt = true;
  261.     
  262.     // and light them up
  263.     SWSetLightingSquare(swp, col - 1, row - 1, lightColor, lightLevelBorder, blendIt, true);
  264.     SWSetLightingSquare(swp, col    , row - 1, lightColor, lightLevelMiddle, blendIt, true);
  265.     SWSetLightingSquare(swp, col + 1, row - 1, lightColor, lightLevelBorder, blendIt, true);
  266.     SWSetLightingSquare(swp, col - 1, row    , lightColor, lightLevelMiddle, blendIt, true);
  267.     SWSetLightingSquare(swp, col    , row    , lightColor, lightLevelMiddle, blendIt, true);
  268.     SWSetLightingSquare(swp, col + 1, row    , lightColor, lightLevelMiddle, blendIt, true);
  269.     SWSetLightingSquare(swp, col - 1, row + 1, lightColor, lightLevelBorder, blendIt, true);
  270.     SWSetLightingSquare(swp, col    , row + 1, lightColor, lightLevelMiddle, blendIt, true);
  271.     SWSetLightingSquare(swp, col + 1, row + 1, lightColor, lightLevelBorder, blendIt, true);
  272.  
  273.     if (BigLight)
  274.     {   /// If BigLight is true then we make a really big light that 
  275.         /// lights up a 5x5 area of tiles rather than 3x3
  276.         int lightLevelEdgeCorner = lightLevelBorder + 2;
  277.         int lightLevelEdgeNearCorner = lightLevelBorder + 1;
  278.         int lightLevelEdge = lightLevelBorder + 1;
  279.  
  280.         SWSetLightingSquare(swp, col - 2, row - 2, lightColor, lightLevelEdgeCorner, blendIt, true);
  281.         SWSetLightingSquare(swp, col + 2, row - 2, lightColor, lightLevelEdgeCorner, blendIt, true);
  282.         SWSetLightingSquare(swp, col - 2, row + 2, lightColor, lightLevelEdgeCorner, blendIt, true);
  283.         SWSetLightingSquare(swp, col + 2, row + 2, lightColor, lightLevelEdgeCorner, blendIt, true);
  284.         SWSetLightingSquare(swp, col - 1, row - 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  285.         SWSetLightingSquare(swp, col    , row - 2, lightColor, lightLevelEdge, blendIt, true);
  286.         SWSetLightingSquare(swp, col + 1, row - 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  287.         SWSetLightingSquare(swp, col - 1, row + 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  288.         SWSetLightingSquare(swp, col    , row + 2, lightColor, lightLevelEdge, blendIt, true);
  289.         SWSetLightingSquare(swp, col + 1, row + 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  290.         SWSetLightingSquare(swp, col - 2, row - 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  291.         SWSetLightingSquare(swp, col - 2, row    , lightColor, lightLevelEdge, blendIt, true);
  292.         SWSetLightingSquare(swp, col - 2, row + 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  293.         SWSetLightingSquare(swp, col + 2, row - 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  294.         SWSetLightingSquare(swp, col + 2, row    , lightColor, lightLevelEdge, blendIt, true);
  295.         SWSetLightingSquare(swp, col + 2, row + 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  296.     }
  297.     
  298. }
  299.  
  300.  
  301. ///--------------------------------------------------------------------------------------
  302. ///--------------------------------------------------------------------------------------
  303. /// The Blitting Functions
  304. ///--------------------------------------------------------------------------------------
  305. ///--------------------------------------------------------------------------------------
  306.  
  307.  
  308. #pragma mark ----------- 8 Bit Screen Draw Function -------------
  309. ///--------------------------------------------------------------------------------------
  310. //        BlitPixie8BitLitRectDrawProc
  311. ///--------------------------------------------------------------------------------------
  312.  
  313. SW_FUNC void BlitPixie8BitLitRectDrawProc(
  314.     FramePtr srcFrameP,
  315.     FramePtr dstFrameP,
  316.     Rect* srcRect,
  317.     Rect* dstRect
  318.     )
  319. {
  320.     Rect                     srcBlitRect = *srcRect;
  321.     Rect                     dstBlitRect = *dstRect;
  322.     unsigned long             numBytesPerRow;
  323.     register unsigned char     *tableAtLevelAndIndex;
  324.     int                     startRow, endRow, startCol, endCol, startSrcRow, startSrcCol;
  325.     int                     row, col, index, srcRow, srcCol;
  326.     Rect                     curSrcBlitRect, curDstBlitRect;
  327.     
  328.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  329.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
  330.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  331.  
  332.     BP_CLIP_RECT((&dstFrameP->frameRect), srcBlitRect, dstBlitRect);    
  333.     START_32_BIT_MODE
  334.     
  335.     startRow = dstBlitRect.top / SWLitSquareSize;
  336.     startCol = dstBlitRect.left / SWLitSquareSize;
  337.     endRow = (dstBlitRect.bottom / SWLitSquareSize) + 1 ;
  338.     endCol = (dstBlitRect.right / SWLitSquareSize) + 1;
  339.  
  340.     startSrcRow = srcBlitRect.top / SWLitSquareSize;
  341.     startSrcCol = srcBlitRect.left / SWLitSquareSize;
  342.     
  343.     for (row = startRow, srcRow = startSrcRow; row <= endRow; row++, srcRow++) {
  344.         for (col = startCol, srcCol = startSrcCol; col <= endCol; col++, srcCol++) {
  345.             index = ((row * gLightingSquareColumns) + col);
  346.             tableAtLevelAndIndex = &g8BitTranslucencyTable[(gLitSquareLevelTable[index] << 16) | (gLitSquareColorTable[index] << 8)];
  347.             
  348.             curSrcBlitRect.top = srcRow * SWLitSquareSize;
  349.             curSrcBlitRect.bottom = curSrcBlitRect.top + SWLitSquareSize;
  350.             curSrcBlitRect.left = srcCol * SWLitSquareSize;
  351.             curSrcBlitRect.right = curSrcBlitRect.left + SWLitSquareSize;
  352.             curDstBlitRect.top = row * SWLitSquareSize;
  353.             curDstBlitRect.bottom = curDstBlitRect.top + SWLitSquareSize;
  354.             curDstBlitRect.left = col * SWLitSquareSize;
  355.             curDstBlitRect.right = curDstBlitRect.left + SWLitSquareSize;
  356.             
  357.             SectRect(&dstBlitRect, &curDstBlitRect, &curDstBlitRect);
  358.             SectRect(&srcBlitRect, &curSrcBlitRect, &curSrcBlitRect);
  359.             
  360.                 // calculate the number of bytes in each row to be copied
  361.             numBytesPerRow = (curDstBlitRect.right - curDstBlitRect.left);
  362.  
  363.             BlitPixieLit8Bit(
  364.                     // calculate the address of the first byte of the source
  365.                 (unsigned long *)(srcFrameP->frameBaseAddr + 
  366.                     (srcFrameP->scanLinePtrArray[curSrcBlitRect.top - srcFrameP->frameRect.top]) + 
  367.                     curSrcBlitRect.left),
  368.  
  369.                     // calculate the address of the first byte of the destination
  370.                 (unsigned long *)(dstFrameP->frameBaseAddr + 
  371.                     (dstFrameP->scanLinePtrArray[curDstBlitRect.top]) + curDstBlitRect.left),
  372.  
  373.                     // calculate the number of rows to blit
  374.                 curDstBlitRect.bottom - curDstBlitRect.top,
  375.  
  376.                     // number of bytes in a row (also the number of pixels to be copied)
  377.                 numBytesPerRow,
  378.  
  379.                 srcFrameP->frameRowBytes,
  380.                 dstFrameP->frameRowBytes,
  381.                 tableAtLevelAndIndex
  382.                 );
  383.         }
  384.     }
  385.     
  386.     END_32_BIT_MODE
  387. }
  388.  
  389. ///--------------------------------------------------------------------------------------
  390. //        LightingConvertChar
  391. ///--------------------------------------------------------------------------------------
  392.  
  393. SW_FUNC unsigned char SWInline LightingConvertChar (
  394.     register unsigned char srcPixel, 
  395.     register unsigned char *tableAtLevelAndIndex) {
  396.     
  397.     // Easy, just the pixel in the table
  398.     return tableAtLevelAndIndex[srcPixel];
  399. }
  400.  
  401.  
  402. ///--------------------------------------------------------------------------------------
  403. //        LightingConvertShort
  404. ///--------------------------------------------------------------------------------------
  405.  
  406. SW_FUNC unsigned short  LightingConvertShort (
  407.     register unsigned short srcPixel, 
  408.     register unsigned char *tableAtLevelAndIndex) {
  409.     
  410.     register unsigned long colorValue;
  411.     register unsigned long result = 0L;
  412.     
  413.     colorValue = tableAtLevelAndIndex[srcPixel >> 8];
  414.     result = colorValue << 8;
  415.     colorValue = tableAtLevelAndIndex[(srcPixel  & 0x00FF)];
  416.     result = colorValue | result;
  417.     return result;
  418. }
  419.  
  420. #if USE_PPC_ASSEMBLY && __MWERKS__ >= 0x1800    // Only compiles under CW Pro
  421.  
  422. ///--------------------------------------------------------------------------------------
  423. //        LightingConvertLong
  424. ///--------------------------------------------------------------------------------------
  425.  
  426. SW_FUNC unsigned long  LightingConvertLong (
  427.     register unsigned long srcPixel, 
  428.     register unsigned char *tableAtLevelAndIndex) {
  429.     
  430.     register unsigned long colorValue;
  431.     register unsigned long result;
  432.     
  433.     colorValue = tableAtLevelAndIndex[srcPixel >> 24];    // look up the colored pixel
  434.     result = colorValue << 24;                            // and shift it back into place as our high end pixel
  435.     colorValue = tableAtLevelAndIndex[((srcPixel >> 16)  & 0x000000FF)];
  436.     __rlwimi(    result, colorValue, 16, 8, 15    );
  437.     colorValue = tableAtLevelAndIndex[((srcPixel >> 8)  & 0x000000FF)];
  438.     __rlwimi(    result, colorValue, 8, 16, 23    );
  439.     colorValue = tableAtLevelAndIndex[(srcPixel  & 0x000000FF)];
  440.     __rlwimi(    result, colorValue, 0, 24, 31    );
  441.         
  442.     // return the four pixels we've computed
  443.     return result;    
  444. }
  445.  
  446. #else /* USE_PPC_ASSEMBLY && __MWERKS__ >= 0x1800 */
  447.  
  448. ///--------------------------------------------------------------------------------------
  449. //        LightingConvertLong
  450. ///--------------------------------------------------------------------------------------
  451.  
  452. SW_FUNC unsigned long SWInline LightingConvertLong (
  453.     register unsigned long srcPixel, 
  454.     register unsigned char *tableAtLevelAndIndex) {
  455.     
  456.     register unsigned long colorValue;
  457.     register unsigned long result = 0L;
  458.     
  459.     colorValue = tableAtLevelAndIndex[srcPixel >> 24];    // look up the colored pixel
  460.     result = colorValue << 24;                            // and shift it back into place as our high end pixel
  461.     colorValue = tableAtLevelAndIndex[((srcPixel >> 16)  & 0x000000FF)];
  462.     result = (colorValue << 16) | result;
  463.     colorValue = tableAtLevelAndIndex[((srcPixel >> 8)  & 0x000000FF)];
  464.     result = (colorValue << 8) | result;
  465.     colorValue = tableAtLevelAndIndex[(srcPixel  & 0x000000FF)];
  466.     result = colorValue | result;
  467.         
  468.     // return the four pixels we've computed
  469.     return result;    
  470. }
  471.  
  472. #endif /* USE_PPC_ASSEMBLY */
  473.  
  474. ///--------------------------------------------------------------------------------------
  475. //        BlitPixieLit8Bit
  476. ///--------------------------------------------------------------------------------------
  477.  
  478.  
  479. SW_FUNC void BlitPixieLit8Bit(
  480.     unsigned long *srcPixelP,
  481.     unsigned long *dstPixelP,
  482.     register unsigned long rowsToCopy,
  483.     register unsigned long numBytesPerRow,
  484.     register unsigned long srcOffset,
  485.     register unsigned long dstOffset,
  486.     register unsigned char *tableAtLevelAndIndex)
  487. {
  488.     register long index;
  489.     register unsigned long *startSrcPixelP;
  490.     register unsigned long *startDstPixelP;
  491.     
  492.         
  493.     startSrcPixelP = srcPixelP;
  494.     startDstPixelP = dstPixelP;
  495.  
  496.     while (rowsToCopy--)
  497.     {
  498.         register fourblits = (numBytesPerRow >> 2);
  499.         
  500.         srcPixelP = startSrcPixelP;
  501.         dstPixelP = startDstPixelP;
  502.         
  503.         for (index = 0; index < fourblits; index++) {
  504.             dstPixelP[index] = LightingConvertLong(srcPixelP[index], tableAtLevelAndIndex);
  505.         }
  506.  
  507.         srcPixelP += fourblits;
  508.         dstPixelP += fourblits;
  509.         
  510. #ifdef MWERKS        
  511.         if (numBytesPerRow & 0x2)
  512.             *((unsigned short *) dstPixelP)++ = LightingConvertShort(*((unsigned short *) srcPixelP)++, tableAtLevelAndIndex);
  513.         if (numBytesPerRow & 0x1)
  514.             *((unsigned char *) dstPixelP)++ = LightingConvertChar(*((unsigned char *) srcPixelP)++, tableAtLevelAndIndex);
  515. #else        
  516.         if (numBytesPerRow & 0x2)
  517.         {
  518.                 // Work around Think C's inability to do simple typecasting - Vern
  519.             *(unsigned short *)dstPixelP = LightingConvertShort(*(unsigned short *)srcPixelP, tableAtLevelAndIndex);
  520.             srcPixelP = (unsigned long *)(((unsigned short *)srcPixelP) + 1);
  521.             dstPixelP = (unsigned long *)(((unsigned short *)dstPixelP) + 1);
  522.         }
  523.         if (numBytesPerRow & 0x1)
  524.         {
  525.             *(unsigned char *)dstPixelP = LightingConvertChar(*(unsigned char *)srcPixelP, tableAtLevelAndIndex);
  526.             srcPixelP = (unsigned long *)(((unsigned char *)srcPixelP) + 1);
  527.             dstPixelP = (unsigned long *)(((unsigned char *)dstPixelP) + 1);
  528.         }
  529. #endif
  530.  
  531.             // bump to next row    
  532. #ifdef MWERKS
  533.         (char *)startSrcPixelP += srcOffset;
  534.         (char *)startDstPixelP += dstOffset;
  535. #else
  536.         startSrcPixelP = (unsigned long *)(((char *)startSrcPixelP) + srcOffset);
  537.         startDstPixelP = (unsigned long *)(((char *)startDstPixelP) + dstOffset);
  538. #endif
  539.     }
  540. }
  541.  
  542. ///--------------------------------------------------------------------------------------
  543. ///--------------------------------------------------------------------------------------
  544. ///--------------------------------------------------------------------------------------
  545. ///--------------------------------------------------------------------------------------
  546. ///--------------------------------------------------------------------------------------
  547. /// 16 Bit Versions
  548.  
  549. #pragma mark ----------- 16 Bit Screen Draw Function -------------
  550. ///--------------------------------------------------------------------------------------
  551. //        BlitPixie16BitLitRectDrawProc
  552. ///--------------------------------------------------------------------------------------
  553.  
  554. SW_FUNC void BlitPixie16BitLitRectDrawProc(
  555.     FramePtr srcFrameP,
  556.     FramePtr dstFrameP,
  557.     Rect* srcRect,
  558.     Rect* dstRect
  559.     )
  560. {
  561.     Rect                     srcBlitRect = *srcRect;
  562.     Rect                     dstBlitRect = *dstRect;
  563.     unsigned long             numBytesPerRow;
  564.     int                     startRow, endRow, startCol, endCol, startSrcRow, startSrcCol;
  565.     int                     row, col, index, srcRow, srcCol;
  566.     Rect                     curSrcBlitRect, curDstBlitRect;
  567.  
  568.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  569.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 16);
  570.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 16);
  571.  
  572.     BP_CLIP_RECT((&dstFrameP->frameRect), srcBlitRect, dstBlitRect);
  573.     START_32_BIT_MODE
  574.  
  575.     startRow = dstBlitRect.top / SWLitSquareSize;
  576.     startCol = dstBlitRect.left / SWLitSquareSize;
  577.     endRow = (dstBlitRect.bottom / SWLitSquareSize) + 1 ;
  578.     endCol = (dstBlitRect.right / SWLitSquareSize) + 1;
  579.  
  580.     startSrcRow = srcBlitRect.top / SWLitSquareSize;
  581.     startSrcCol = srcBlitRect.left / SWLitSquareSize;
  582.  
  583.     for (row = startRow, srcRow = startSrcRow; row <= endRow; row++, srcRow++ ) {
  584.         for (col = startCol, srcCol = startSrcCol; col <= endCol; col++, srcCol++ ) {
  585.             index = ((row * gLightingSquareColumns) + col);
  586.  
  587.             curSrcBlitRect.top = srcRow * SWLitSquareSize;
  588.             curSrcBlitRect.bottom = curSrcBlitRect.top + SWLitSquareSize;
  589.             curSrcBlitRect.left = srcCol * SWLitSquareSize;
  590.             curSrcBlitRect.right = curSrcBlitRect.left + SWLitSquareSize;
  591.             curDstBlitRect.top = row * SWLitSquareSize;
  592.             curDstBlitRect.bottom = curDstBlitRect.top + SWLitSquareSize;
  593.             curDstBlitRect.left = col * SWLitSquareSize;
  594.             curDstBlitRect.right = curDstBlitRect.left + SWLitSquareSize;
  595.  
  596.             SectRect(&dstBlitRect, &curDstBlitRect, &curDstBlitRect);
  597.             SectRect(&srcBlitRect, &curSrcBlitRect, &curSrcBlitRect);
  598.  
  599.             numBytesPerRow = curDstBlitRect.right - curDstBlitRect.left;
  600.  
  601.             if (numBytesPerRow > 0)  // don't draw when the intersection is null...
  602.                 BlitPixieLit16Bit(
  603.                         // calculate the address of the first byte of the source
  604.                     (unsigned short *)(srcFrameP->frameBaseAddr +
  605.  
  606.     (srcFrameP->scanLinePtrArray[curSrcBlitRect.top - srcFrameP->frameRect.top]) +
  607.                         (curSrcBlitRect.left << 1)),
  608.  
  609.                         // calculate the address of the first byte of the destination
  610.                     (unsigned short *)(dstFrameP->frameBaseAddr +
  611.  
  612.     (dstFrameP->scanLinePtrArray[curDstBlitRect.top]) +
  613.                         (curDstBlitRect.left << 1)),
  614.  
  615.                         // number of bytes in a row (also the number of pixels to be copied)
  616.                     numBytesPerRow,
  617.                     curDstBlitRect.bottom - curDstBlitRect.top,
  618.  
  619.                     srcFrameP->frameRowBytes,
  620.                     dstFrameP->frameRowBytes,
  621.                     gLitSquareColorTable[index],
  622.                     gLitSquareLevelTable[index]
  623.                     );
  624.         }
  625.     }
  626.  
  627.     END_32_BIT_MODE
  628. }
  629.  
  630. #if USE_PPC_ASSEMBLY
  631.  
  632. // Some defines to make this easier to read
  633. #define lookup_offset1 alpha
  634. #define lookup_offset2 r11
  635. #define lookup_offset3 r12
  636. #define tablePointer r13
  637. #define tmp1 r0
  638. #define tmp2 r31
  639. #define tmp3 r30
  640.  
  641. void asm BlitPixieLit16Bit(
  642.     register unsigned short *srcPtr,
  643.     register unsigned short *dstPtr,
  644.     register unsigned long width,
  645.     register unsigned long height,
  646.     register unsigned long srcRowBytes,
  647.     register unsigned long dstRowBytes,
  648.     register unsigned long color,
  649.     register unsigned long alpha)
  650. {
  651.     stw     tmp2,-4(SP)    //store temp vars on the stack 
  652.     stw     tmp3,-8(SP)
  653.     stw     lookup_offset2,-12(SP)
  654.     stw     lookup_offset3,-16(SP)
  655.     stw     tablePointer,-20(SP)
  656.  
  657.     // Load a register with a pointer to our table
  658.     lwz      tablePointer, g16BitTranslucencyTable(RTOC)
  659.     lwz      tablePointer, 0(tablePointer)
  660.     
  661.     // We need to make the rowBytes be rowBytes - width because we are using
  662.     // preincrements when getting and setting the pixels
  663.     add        tmp1, width, width                //adjust for pixels being 2 bytes long
  664.     sub        srcRowBytes,srcRowBytes,tmp1    //calculateoffsets to the next row
  665.     sub        dstRowBytes,dstRowBytes,tmp1
  666.  
  667.     //adjust the pointers so we can use pre-increments
  668.     subi    srcPtr,srcPtr,2
  669.     subi    dstPtr,dstPtr,2
  670.         
  671.     // Set up the offsets into the blending table for each of our R, G, and B lookups
  672.     // by setting the high order five bits to the alpha color
  673.     // Note that these high order bits never get changed as we
  674.     // work on our pixels, so the alpha (translucency level)
  675.     // stays the same
  676.     rlwinm    lookup_offset3,alpha,10,17,21 
  677.     mr        lookup_offset2,lookup_offset3
  678.     mr        lookup_offset1,lookup_offset3
  679.     
  680.     rlwimi    lookup_offset3, color, 5, 22, 26        //blue channel source
  681.     rlwimi    lookup_offset2, color, 0, 22, 26        //green channel source
  682.     rlwimi    lookup_offset1, color, 27, 22, 26    //red channel source
  683.         
  684.     
  685. @yloop
  686.     mtctr     width                                    //set the ctr to so we copy do WIDTH number of pixels
  687.  
  688.         @xloop
  689.             lhzu    tmp1,2(srcPtr)                    //load the source and destination colour
  690.             
  691.             rlwimi    lookup_offset3,tmp1,0,27,31        //blue channel destination    
  692.             rlwimi    lookup_offset2,tmp1,27,27,31    //green channel destination
  693.             rlwimi    lookup_offset1,tmp1,22,27,31    //red channel destination
  694.             
  695.             lbzx    tmp3,tablePointer,lookup_offset3    //load blended blue channel
  696.             lbzx    tmp2,tablePointer,lookup_offset2    //load blended green channel
  697.             lbzx    tmp1,tablePointer,lookup_offset1    //load blended red channel
  698.             
  699.             rlwimi    tmp3,tmp2,5,22,26                //insert green channel into result
  700.             rlwimi    tmp3,tmp1,10,17,21                //insert red channel into result
  701.             
  702.             sthu    tmp3,2(dstPtr)                    //store result
  703.  
  704.         @endOfBlitXLoop
  705.             bdnz    @xloop                            // decrement the ctr and see if we're done                
  706.     
  707.     // Now we move the pointers forward to the next row
  708.     add        srcPtr,srcPtr,srcRowBytes
  709.     add        dstPtr,dstPtr,dstRowBytes    
  710.     
  711.     //and if we haven't finished, continue
  712.     subi    height,height,1            
  713.     cmpwi    height,0
  714.     bne        @yloop    
  715.     
  716.     lwz     tmp2,-4(SP)            //clean up, restore registers we've been using
  717.     lwz     tmp3,-8(SP)
  718.     lwz     lookup_offset2,-12(SP)
  719.     lwz     lookup_offset3,-16(SP)
  720.     lwz     tablePointer,-20(SP)
  721.     
  722.     blr
  723.  
  724. }
  725.  
  726. #undef lookup_offset1
  727. #undef lookup_offset2
  728. #undef lookup_offset3
  729. #undef tmp1
  730. #undef tmp2
  731. #undef tmp3
  732. #undef height
  733. #undef width
  734.  
  735. #else /* USE_PPC_ASSEMBLY */
  736.  
  737. // Here is a C version of the above function.  
  738. // it's about 20% slower than the assembly one.
  739.  
  740. // Note: don't declare the args to this function as "register".  If you do, then
  741. // it won't compile properly for the 68K.
  742.  
  743. void BlitPixieLit16Bit (
  744.      unsigned short *srcPtr,
  745.      unsigned short *dstPtr,
  746.      unsigned long width,
  747.      unsigned long height,
  748.      unsigned long srcRowBytes,
  749.      unsigned long dstRowBytes,
  750.      unsigned long color,
  751.      unsigned long alpha) {
  752.     
  753.      int xx, yy;
  754.      unsigned long lookup_offset_blue, lookup_offset_green, lookup_offset_red;
  755.      unsigned long final_red, final_green, final_result;
  756.     short curSource;
  757.  
  758.     srcRowBytes -= width * 2;
  759.     dstRowBytes -= width * 2;
  760.  
  761.     lookup_offset_blue = lookup_offset_green = lookup_offset_red = alpha << 10;
  762.     lookup_offset_blue |= (color << 5) & 0x03E0;
  763.     lookup_offset_green |= color & 0x03E0;
  764.     lookup_offset_red |= (color >> 5) & 0x03E0;
  765.  
  766.     for (yy = 0; yy < height; yy++) {
  767.         for (xx = 0; xx < width; xx++) {
  768.             curSource = *srcPtr++;
  769.             
  770.             lookup_offset_blue &= 0xFFE0;
  771.             lookup_offset_green &= 0xFFE0;
  772.             lookup_offset_red &= 0xFFE0;
  773.  
  774.             lookup_offset_blue |= curSource & 0x001F;
  775.             lookup_offset_green |= (curSource >> 5) & 0x001F;
  776.             lookup_offset_red |= (curSource >> 10) & 0x001F;
  777.  
  778.             final_red = g16BitTranslucencyTable[lookup_offset_red];
  779.             final_green = g16BitTranslucencyTable[lookup_offset_green];
  780.             final_result = g16BitTranslucencyTable[lookup_offset_blue];
  781.  
  782.             final_result |= final_green << 5;
  783.             final_result |= final_red << 10;
  784.  
  785.             *dstPtr++ = final_result;
  786.         }
  787.         
  788. #ifdef MWERKS
  789.         (char *)srcPtr += srcRowBytes;
  790.         (char *)dstPtr += dstRowBytes;
  791. #else
  792.         srcPtr = (unsigned short *)(((char *)srcPtr) + srcRowBytes);
  793.         dstPtr = (unsigned short *)(((char *)dstPtr) + dstRowBytes);
  794. #endif
  795.     }
  796.  
  797. }
  798. #endif /* USE_PPC_ASSEMBLY */
  799.